<!--编辑场景-->
<template xmlns:background-color="http://www.w3.org/1999/xhtml">
  <lay-card ref="rightEdit" class="wrapper-fullscreen" style="height: 99%">
    <lay-split-panel minSize="10px">
      <lay-split-panel-item>
        <lay-card style="margin-top: 10px">
          <lay-quote size="sm">
            <lay-row space="20">
              <lay-col md="16">
                <lay-tooltip :visible="visible" trigger="click" :content="tips" :isDark="false">
                <h3>
                  <a @mouseenter="visible=true" @mouseleave="visible=false">
                    <span>场景【{{scene_name}}】基础信息:</span>
<!--                    <lay-icon size="sm" type="layui-icon-help"></lay-icon>-->
                  </a>
                </h3>
                </lay-tooltip>
              </lay-col>
              <lay-col md="20">
                <lay-dropdown updateAtScroll placement="bottom-end" ref="manualRefLeft" :clickOutsideToClose="false">
                  <lay-button size="sm">添加表</lay-button>
                  <template #content>
                    <div style="width: 500px">
                      <VirtualTree
                        :scrollHeight="'400px'"
                        :showCheckbox="true"
                        :page="'scene'"
                        :target="'left'"
                        @insertTables="insertTables"
                        @cancelCheck="cancelCheckLeft"
                        style="margin-top: 10px"
                      ></VirtualTree>
                    </div>
                  </template>
                </lay-dropdown>
                <lay-dropdown
                    :trigger="['click', 'hover']"
                    updateAtScroll
                    placement="left-start"
                >
                  <lay-button size="sm">规则中转站</lay-button>
                  <template #content>
                    <HistoryRulesPage
                        :allowRelate="true"
                        @relateFields="relateOtherField"
                    ></HistoryRulesPage>
                  </template>
                </lay-dropdown>

                <lay-button size="sm" type="normal" @click="changeUploadVisible">上传文件</lay-button>
                <lay-tooltip :visible="sql_tip_visible" trigger="click" :content="sql_tips" :isDark="false">
                  <a @mouseenter="sql_tip_visible=true" @mouseleave="sql_tip_visible=false">
                    <lay-icon size="sm" type="layui-icon-help-circle" style="margin-left: 5px"></lay-icon>
                  </a>
                </lay-tooltip>
                <lay-layer v-model="upload_visible" :title="'上传文件'" :shade="true" :area="['35%','70%']">
                  <div style="padding: 20px;">
                    <lay-row space="10">
                      <lay-col md="24">
                        <p style="color: blue; background-color: #a6e22e; font-weight: 700">仅支持INSERT语句；请删掉注释信息</p>
                        <p style="color: red; font-weight: 700">由于数据库存储长度有限，每个字段最多支持100个遍历值，超出部分将直接舍弃；请注意文件中不要对同一张表有过多的INSERT语句！！！</p>
                      </lay-col>
                    </lay-row>
                    <lay-row space="10">
                      <lay-col md="24">
                        <lay-form-item label="绑定数据库">
                          <lay-tree-select
                              size="sm"
                              v-model="db_id"
                              :data="dataSources"
                              :multiple="false"
                              style="width: 90%"
                          ></lay-tree-select>
                        </lay-form-item>
                      </lay-col>
                    </lay-row>
                    <lay-row space="10">
                      <lay-col md="24">
                        <lay-form-item label="选择文件">
                          <lay-upload :drag="true" v-model="file" field="file" :multiple="false" :auto="false">
                            <template #preview>
                              {{ file[0]?.name }}
                            </template>
                          </lay-upload>
                        </lay-form-item>
                      </lay-col>
                    </lay-row>
                    <lay-row space="10">
                      <lay-col md="24">
                        <lay-button size="sm" type="normal" @click="selectFile" style="float: right">上&nbsp;&nbsp;传</lay-button>
                      </lay-col>
                    </lay-row>
                  </div>
                </lay-layer>
                <lay-button size="sm" type="normal" @click="saveScene" style="margin-left: 30px">保存场景</lay-button>
                <lay-button size="sm" type="normal" @click="createSql">数据生成</lay-button>
              </lay-col>
            </lay-row>
          </lay-quote>
        </lay-card>
      </lay-split-panel-item>
    </lay-split-panel>
    <lay-split-panel>
      <lay-layer v-model="progress_visible" :title="'SQL文件解析中....'" :shade="true" :area="['25%','20%']">
        <div style="padding: 20px;">
          <lay-row space="10">
            <lay-progress
                style="margin-top: 15px"
                :percent="percent"
                :show-text="true"
            ></lay-progress>
          </lay-row>
        </div>
      </lay-layer>
      <lay-split-panel-item>
        <lay-scroll :height="scrollHeight">
          <lay-row>
            <lay-col span="24">
              <lay-panel
                v-for="(tableData, index) in totalLeft"
                :key="tableData"
                style="margin: 10px; padding: 10px"
              >
                <lay-button
                  size="xs"
                  style="float: right"
                  @click="moveTable(tableData, 'left')"
                >移到右边</lay-button>
                <lay-button
                    style="float: right;margin-right: 10px"
                    :disabled="isMoveDisable(index, 'left')"
                    size="xs"
                    @click="moveTablePos(tableData, index, 'left', 'down')"
                >向下移动</lay-button>
                <lay-button
                    style="float: right;margin-right: 10px"
                    :disabled="index == 0"
                    size="xs"
                    @click="moveTablePos(tableData, index, 'left', 'up')"
                >向上移动</lay-button>
                <lay-button
                  size="xs"
                  style="float: right;margin-right: 10px"
                  @click="deleteTable(tableData, 'left')"
                >移除</lay-button>
                <br/>
                <TableBasicInfo
                  :mode="'scene'"
                  :tableHeight="tableHeight"
                  :tableData="tableData"
                  @dependTable="getDependTableColumns(index, 'left')"
                  @setEditFlag="editFlag = true"
                ></TableBasicInfo>
              </lay-panel>
            </lay-col>
          </lay-row>
        </lay-scroll>
      </lay-split-panel-item>
      <lay-split-panel-item>
        <lay-scroll :height="scrollHeight">
          <lay-row>
            <lay-col span="24">
              <lay-panel
                v-for="(tableData, index) in totalRight"
                :key="tableData"
                style="margin: 10px; padding: 10px"
              >
                <lay-button size="xs" @click="moveTable(tableData, 'right')">移到左边</lay-button>
                <lay-button
                    :disabled="index == 0"
                    size="xs"
                    @click="moveTablePos(tableData, index, 'right', 'up')"
                >向上移动</lay-button>
                <lay-button
                    :disabled="isMoveDisable(index, 'right')"
                    size="xs"
                    @click="moveTablePos(tableData, index, 'right', 'down')"
                >向下移动</lay-button>
                <lay-button size="xs" @click="deleteTable(tableData, 'right')">移除</lay-button>
                <TableBasicInfo
                    :mode="'scene'"
                    :tableHeight="tableHeight"
                    :tableData="tableData"
                    @setEditFlag="editFlag = true"
                    @dependTable="getDependTableColumns(index)"
                ></TableBasicInfo>
              </lay-panel>
            </lay-col>
          </lay-row>
        </lay-scroll>
      </lay-split-panel-item>
    </lay-split-panel>
  </lay-card>
</template>

<script lang="ts">
import TableBasicInfo from "../../../../components/database/TableBasicInfo.vue";
import SourcesTree from "../../../../components/database/SourcesTree.vue";
import ReviewData from "../../../../components/scene/data/ReviewData.vue";

export default {
  name: "EditScene",
  components: {
    TableBasicInfo,
    SourcesTree,
    ReviewData
  }
}
</script>

<script lang="ts" setup>
import {getCurrentInstance, h, onBeforeMount, onBeforeUnmount, reactive, ref} from "vue";
import {useRoute} from "vue-router";
import {addSceneSQLApi, getTableTreeApi, querySceneDetailApi, querySQLParserApi, updateSceneApi} from "../../../../api/module/scene";
import {layer} from "@layui/layui-vue";
import ProductData from "../../../../components/scene/data/ProductData.vue";
import {getAllLinksTress, queryAllColumn} from "../../../../api/module/db";
import {notify} from "../../../../untils/tip";
import VirtualTree from "../../../../components/database/VirtualTree.vue";
import HistoryRulesPage from "../../../../components/database/HistoryRules.vue";

const route = useRoute();
const node: any = reactive({dict: {scene_id: '', scene_name: ''}});
const timer = ref();
const progress_visible = ref(false);

onBeforeMount(() => {
    node.dict = route.params;

    let countProduct = 0;
    timer.value = setInterval(()=>{
      querySQLParserStatus(countProduct);
      countProduct ++;
      if(countProduct > 5400){
        clearInterval(timer.value);
        timer.value = '';
        notify("failed", "超时退出！");
        querySceneDetail();
      }
    }, 500);
});

const scene_name = ref('');
const percent = ref(0);
const totalLeft: any = ref([]);
const totalRight: any = ref([]);
const manualRefRight = ref();
const manualRefLeft = ref();
const editFlag = ref(false); // 编辑状态，为true要自动保存
const visible = ref(false);
const sql_tip_visible = ref(false);
const upload_visible = ref(false);
const db_id = ref('')
const dataSources = ref();
const file = ref([])
const tips = ref('表字段关联规则是：下面的表/字段可以关联上面的表/字段');
const sql_tips = ref("将上传的SQL文件解析成场景，上传的文件中只能包含INSERT语句，每条语句以';'分隔")

const rightEdit = ref(null);
const scrollHeight = ref('600px');

const tableHeight = ref('400px');

const cancelCheckLeft = () => {
  manualRefLeft.value.hide()
};

const cancelCheckRight = () => {
  manualRefRight.value.hide()
};

// 一键关联规则到其他自动
let instance = getCurrentInstance();

const relateOtherField = (unit: any) => {
  console.log("on-relate-rule submit:", unit);
  instance?.proxy?.$Bus.emit('on-relate-rule', unit);
}

const querySQLParserStatus = async (countProduct: any) => {
  let {result, status, message} = await querySQLParserApi({scene_id: node.dict.scene_id})
  if(status === "success" && result != null && result.progress != 100) {
    percent.value = result.progress;
    if(countProduct === 0) {
      progress_visible.value = true;
    }
  }
  else {
    clearInterval(timer.value);
    timer.value = '';
    await querySceneDetail();
  }
}

const querySceneDetail = async () => {
  progress_visible.value=false;
  layer.load(3);
  let {result, status, message} = await querySceneDetailApi({id: node.dict.scene_id})
  if(status === 'success'){
      scene_name.value = result.scene_name;
      node.dict.scene_name = result.scene_name;
      totalLeft.value = result.insert_table;
      totalRight.value = result.depend_table;
  }else {
    layer.msg(message);
  }
  layer.closeAll();
};

// 检测 依赖表 或 目标表 中是否存在待插入的字段，如存在表，则判断字段是否存在，不存在就追加；如不存在表，就将表信息直接插入即可
const updateOrInsertData = (tableDict: any, tableList: any) => {
  const insertFlag = ref(true);
  const index = ref(0);
  while (index.value < tableList.length){
    const currentTable = tableList[index.value];
    if(tableDict.table === currentTable.table && tableDict.database === currentTable.database){
      const exitCols = ref([]);
      currentTable.column_rule.data_source.forEach((row: any) => {exitCols.value.push(row.data_source)})
      tableDict.column_rule.data_source.forEach((unit: any)=>{
        if(!(unit.data_source in exitCols)){
          currentTable.column_rule.data_source.push(unit)
          editFlag.value = true;   // 修改编辑状态为 true，触发保存
          insertFlag.value = false; // 设置状态：非插入状态
          notify('success', tableDict.id + '追加字段：' + unit.data_source);
        }
      })
      break;
    }
    index.value ++;
  }
  if(insertFlag.value){
    tableList.push(tableDict);
    editFlag.value = true;
    notify('success', tableDict.id + '插入成功！');
  }else {
    notify('success', tableDict.id + '已经插入过了！');
  }
}

// 插入或更新 依赖表/目标表 或其下的字段
const insertTables = (data: any, target: string) => {
  data.forEach(async (unit: any) => {
    let {result, status, message} = await queryAllColumn(unit);
      if(status === 'success'){
        const table_dict: any = reactive({
          id: unit.id,
          db_id: unit.db_id,
          database: unit.database,
          table: unit.table,
          column_rule: result
        })
        console.log('insertTables data : ', table_dict)
        if(target === 'left'){
          // totalLeft.value.push(table_dict);
          updateOrInsertData(table_dict, totalLeft.value)
          cancelCheckLeft();
        }else {
          // totalRight.value.push(table_dict);
          updateOrInsertData(table_dict, totalRight.value)
          cancelCheckRight();
        }
      }else {
        message = unit.id + ":" + message
        notify(status, message);
      }
  })
};

const judgeExit = (node: any) : boolean => {
  let flag = false;
  totalLeft.value.forEach((unit:any)=>{
    if(unit.id === node.id){
      flag = true;
    }
  })
  totalRight.value.forEach((unit:any)=>{
    if(unit.id === node.id){
      flag = true;
    }
  })
  return flag;
}

/*****/
const isMoveDisable = (index: number, flag: string) : boolean => {
  if(flag === 'left'){
    return index === totalLeft.value.length - 1;
  }else {
    return index === totalRight.value.length - 1;
  }
}

/** 表的上下位置移动 **/
const moveTablePos = (table: any, index: number, flag: any, pos: string) => {
  if(pos === 'up'){
    if(flag === 'left'){
      totalLeft.value.splice(index, 1);
      totalLeft.value.splice(index-1, 0, table);
    }else {
      totalRight.value.splice(index, 1);
      totalRight.value.splice(index-1, 0, table);
    }
  }else {
    if(flag === 'left') {
      totalLeft.value.splice(index, 1);
      totalLeft.value.splice(index + 1, 0, table);
    }else {
      totalRight.value.splice(index, 1);
      totalRight.value.splice(index + 1, 0, table);
    }
  }
  notify("success", "表上下交换成功！");
  editFlag.value = true;
}

const moveTable = (table: any, flag: string) => {
  const tableName = table.database + "." + table.table;
  if(flag === 'left'){
    layer.confirm("此表 [" + tableName + "]将移动依赖表最后一个位置，可能会改变表之间生成数据的顺序。你确定移动吗?",
        {
            btn: [
                {
                    text: '确定', callback: (id: number) => {
                        const index = totalLeft.value.indexOf(table);
                        totalLeft.value.splice(index, 1);
                        totalRight.value.push(table);
                        editFlag.value = true;
                        layer.close(id);
                    }
                },
                {
                    text: 'Cancel', callback: (id: number) => {
                        layer.close(id);
                    }
                }
            ]
        }
    )
  }else {
    layer.confirm("此表 [" + tableName + "]将移动目标表第一个位置，可能会改变表之间生成数据的顺序。你确定移动吗?",
        {
            btn: [
                {
                    text: '确定', callback: (id: number) => {
                        const index = totalLeft.value.indexOf(table);
                        totalRight.value.splice(index, 1);
                        totalLeft.value.splice(0, 0, table);
                        editFlag.value = true;
                        layer.close(id);
                    }
                },
                {
                    text: 'Cancel', callback: (id: number) => {
                        layer.close(id);
                    }
                }
            ]
        }
    )
  }
  editFlag.value = true;
};

const deleteTable = (table: any, flag: string) => {
    const tableName = table.database + "." + table.table;
    layer.confirm("你确定要要移除此表 [" + tableName + "]么?",
        {
            btn: [
                {
                    text: 'OK', callback: (id: number) => {
                        if(flag === 'left'){
                            const index = totalLeft.value.indexOf(table);
                            totalLeft.value.splice(index, 1);
                        }else {
                            const index = totalRight.value.indexOf(table);
                            totalRight.value.splice(index, 1);
                        }
                        editFlag.value = true;
                        layer.close(id);
                    }
                },
                {
                    text: 'Cancel', callback: (id: number) => {
                        layer.close(id);
                    }
                }
            ]
        }
    )
};

const saveScene = async () => {
  const sceneDict = reactive({
    id: node.dict.scene_id, type: 'scene_id',
    target: 'content',
    insert_table: totalLeft.value,
    depend_table: totalRight.value
  });
  let {result, status, message} = await updateSceneApi(sceneDict);
  notify(status, "[" + scene_name.value + "]场景保存，" + message);
  editFlag.value = false;
};

// 获取依赖表的分类数
const getDependTableColumns = async (index: number, pos: string = 'right') => {
  const depend_tables: any = ref([]);
  if(pos === 'left'){
    depend_tables.value = totalLeft.value.slice(0, index+1);
    // depend_tables.value.concat(totalRight.value);
    totalRight.value.forEach((unit: any)=>{
      depend_tables.value.push(unit)
    })
  }else {
    depend_tables.value = totalRight.value.slice(0, index+1);
  }
  // 左边可以选择左边之上和右边的表，右边只能选择右边之上的表。都含自身
  const params = reactive({param: {depend_table: depend_tables.value}})
  let {result, status, message} = await getTableTreeApi(params);
  if(status === 'success'){
    localStorage.setItem('scene_depend_tables', JSON.stringify(result));
  }else {
    notify(status, message);
  }
};

const msg_id = ref();

const createSql = () => {
  console.log(node.dict);
  msg_id.value = layer.open({
      type: "page",
      title: "数据生成：设置条件",
      area: ['35%','48%'],
      content: h(ProductData, {
        scene_info: node.dict,
        cancelAction: function (){
          layer.close(msg_id.value)
        }
      })
  })
}

const changeUploadVisible = () => {
  upload_visible.value = !upload_visible.value;

  if(upload_visible.value === true){
    // 弹窗可见，请求一下dataSource
    getTreeDBS();
  }
}

const getTreeDBS = async () => {
  let {result, status, message} = await getAllLinksTress();
  if (status === 'success'){
    dataSources.value = result.children;
  }else {
    layer.msg(message);
  }
};

const selectFile = async () => {
  console.log(db_id.value);
  if(db_id.value === '') {
    layer.msg("请先绑定数据库");
    return;
  }

  if(file.value.length === 0) {
    layer.msg("请选择文件");
    return;
  }

  const formData = new FormData();
  formData.append('db_id', db_id.value);
  formData.append('scene_id', node.dict.scene_id);
  formData.append('file', file.value[0]);

  layer.load(1);
  let {result, status, message} = await addSceneSQLApi(formData);
  if(status === 'failed'){
    layer.msg(message);
  }
  else{
    layer.msg("上传成功")
  }

  layer.closeAll();
  changeUploadVisible();
  location.reload();
}

const confirmClose = () => {
  if(editFlag.value){
    layer.confirm("场景 [" + scene_name.value + "]，尚未保存，是否保存?",
      {
          btn: [
              {
                  text: 'OK', callback: (id: number) => {
                      saveScene();
                      layer.close(id);
                  }
              },
              {
                  text: 'Cancel', callback: (id: number) => {
                      layer.close(id);
                  }
              }
          ]
      }
    )
  }
}

// 销毁前保存
onBeforeUnmount(()=>{
  confirmClose();
  if(instance !== null){
    instance.proxy.$Bus.off('on-relate-rule');
    instance.proxy.$Bus.all.clear();
  }
})
</script>

<style scoped>
.header-button {
  margin-left: 50px;
  margin-top: 5px;
}
</style>